﻿namespace OpenAdmin.Application.Services;

/// <summary>
/// 菜单服务
/// </summary>
public class MenuService : ServiceBase, IMenuService, ITransientDependency
{
    private readonly IRepository<SysMenu, ApplicationDbContextLocator> _menuRepository;
    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="menuRepository"></param>
    public MenuService(IRepository<SysMenu, ApplicationDbContextLocator> menuRepository)
    {
        _menuRepository = menuRepository;
    }
    /// <summary>
    /// 获取菜单列表
    /// </summary>
    /// <returns></returns>
    public async Task<List<MenusResponseDto>> GetMenus()
    {
        var menus = await _menuRepository.Entities.AsQueryable().OrderBy(p => p.Sort).ProjectToType<MenusResponseDto>().ToListAsync();

        var parentMenus = menus.Where(p => p.ParentId == 0).ToList();
        RecursionChildrenMenu(menus, parentMenus);

        return parentMenus;
    }

    /// <summary>
    /// 添加菜单
    /// </summary>
    /// <param name="requestDto"></param>
    /// <returns></returns>
    public async Task AddMenu(AddMenuRequestDto requestDto)
    {
        var menu = _mapper.Map<SysMenu>(requestDto);
        menu.CreateBy = UserIdentity.UserId;
        var menuEntty = await _menuRepository.Entities.AddAsync(menu);

        var permissionRepository = _menuRepository.Change<SysPermission, ApplicationDbContextLocator>();
        var permissionEntry = await permissionRepository.Entities.AddAsync(new SysPermission
        {
            Name = menu.Name,
            Type = SysConst.MENU,
            Remark = menu.Remark,
            CreateBy = UserIdentity.UserId,
        });

        var result = await _menuRepository.SaveChangesAsync();
        result.ThrowIf(p => p == 0, "添加失败");

        var permissionMenuRepository = _menuRepository.Change<SysPermissionMenu, ApplicationDbContextLocator>();
        await permissionMenuRepository.Entities.AddAsync(new SysPermissionMenu
        {
            MenuId = menuEntty.Entity.Id,
            PermissionId = permissionEntry.Entity.Id
        });

        result = await _menuRepository.SaveChangesAsync();
        result.ThrowIf(p => p == 0, "添加失败");
    }

    /// <summary>
    /// 更新菜单
    /// </summary>
    /// <param name="requestDto"></param>
    public async Task EditMenu(EditMenuRequestDto requestDto)
    {
        var menu = await _menuRepository.Entities.FindAsync(requestDto.Id);
        menu.ThrowIfNull("菜单不存在");

        menu.Name = requestDto.Name;
        menu.ParentId = requestDto.ParentId;
        menu.Route = requestDto.Route;
        menu.Icon = requestDto.Icon;
        menu.Enabled = requestDto.Enabled;
        menu.Sort = requestDto.Sort;
        menu.Remark = requestDto.Remark;
        menu.ModifyBy = UserIdentity.UserId;
        menu.ModifyTime = DateTime.Now;

        var uResult = await _menuRepository.SaveChangesAsync();
        uResult.ThrowIf(p => p == 0, "更新失败");
    }

    /// <summary>
    /// 删除菜单
    /// </summary>
    /// <param name="id"></param>
    public async Task DeleteMenu(int id)
    {
        var menu = await _menuRepository.Entities.FindAsync(id);
        menu.ThrowIfNull("菜单不存在");

        _menuRepository.Entities.Remove(menu);

        var permissionMenuRepository = _menuRepository.Change<SysPermissionMenu, ApplicationDbContextLocator>();
        var permisMenu = await permissionMenuRepository.Entities.SingleOrDefaultAsync(po => po.MenuId == menu.Id);
        if (permisMenu != null)
        {
            permissionMenuRepository.Entities.Remove(permisMenu);

            var permissionRepository = _menuRepository.Change<SysPermission, ApplicationDbContextLocator>();
            var permission = await permissionRepository.Entities.SingleOrDefaultAsync(p => p.Id == permisMenu.PermissionId);
            if (permission != null)
            {
                permissionRepository.Entities.Remove(permission);
            }
        }
        var dResult = await _menuRepository.SaveChangesAsync();
        dResult.ThrowIf(p => p == 0, "删除失败");
    }

    #region Private Methods
    /// <summary>
    /// 递归子菜单项
    /// </summary>
    /// <param name="all"></param>
    /// <param name="parent"></param>
    private void RecursionChildrenMenu(List<MenusResponseDto> all, List<MenusResponseDto> parent)
    {
        foreach (var item in parent)
        {
            var subMenus = all.Where(p => p.ParentId == item.Id).ToList();
            foreach (var subMenu in subMenus)
            {
                item.Children = item.Children == null ? new List<MenusResponseDto>() : item.Children;
                item.Children.Add(subMenu);
            }
            GetAllParentIds(item, all);
            RecursionChildrenMenu(all, subMenus);
        }
    }
    /// <summary>
    /// 获取所有的父级菜单
    /// </summary>
    /// <param name="item"></param>
    /// <param name="all"></param>
    private void GetAllParentIds(MenusResponseDto item, List<MenusResponseDto> all)
    {
        if (item.ParentId == 0)
        {
            item.ParentIds.Add(0);
        }
        var curParent = all.FirstOrDefault(p => p.Id == item.ParentId);
        while (curParent != null)
        {
            item.ParentIds.Add(curParent.Id);
            curParent = all.FirstOrDefault(p => p.Id == curParent.ParentId);
        }
        item.ParentIds.Reverse();
    }
    #endregion
}
